﻿using System;
// 事件一种引用类型，实际上是一种特殊的委托。
// 事件的本质是委托字段的一个包装器，对委托字段的访问起限制作用
// 委托是一种特殊的引用类型，声明放在类的里面/外面(共享)，事件作为委托的包装器其声明一般要放在类里面
namespace test
{
    class TestEvent
    {
        static void Main(string[] args)
        {
            Stock stock = new Stock() { Price = 98 };
            Messenger messenger = new Messenger();
            stock.PriceChanged += messenger.OnPriceChanged;
            stock.Price = 100;
        }
    }

    // record类型可以简化定义
    // record PriceChangedEventArgs(int? OldPrice, int? Price) : EventArgs;
    class PriceChangedEventArgs : EventArgs
    {
        // 只读属性/只读字段在构造函数或声明时初始化
        // 只读属性:对外暴露的不可变数据;只读字段:内部使用的不可变字段
        public int? Price { get; }
        public int? OldPrice { get; }
        public PriceChangedEventArgs(int? oldPrice, int? price)
        {
            this.OldPrice = oldPrice;
            this.Price = price;
        }
    }
    class Stock
    {
        //泛型版本，可以传递自定义数据EventHandler<T>
        public event EventHandler<PriceChangedEventArgs> PriceChanged;
        // 默认版本，事件不需要额外数据
        // public delegate void EventHandler(object? sender, EventArgs e);
        private int? _price;
        public int? Price
        {
            get { return _price; }
            set
            {
                if (value != _price)
                {
                    int? oldPrice = _price;
                    _price = value;
                    PriceChanged?.Invoke(this, new PriceChangedEventArgs(oldPrice, _price));
                }
            }
        }
    }
    class Messenger
    {
        public void OnPriceChanged(object? sender, EventArgs e)
        {
            System.Console.WriteLine($"Stock price changed from {e.OldPrice} to {e.Price}");
        }
    }

}